#include "stdafx.h"
#include "mainwindow.h"
#include <QPushButton>
#include <QApplication>
#include <QTimer>
#include "http_service.h"

static bool not_found(HttpRequest&, HttpResponse& res) {
    acl::string buf("Not found!\r\n");
    res.setStatus(404);
    return res.write(buf, buf.size());
}

static bool handleDownload(MainWindow& w, const char* path,
        HttpRequest& req, HttpResponse& res) {
    qDebug() << "Begin to get file for path: " << path;
    acl::string tmp(path);
    const auto& tokens = tmp.split2("/");
    const std::string* file_path = w.get_filepath(tokens[0].c_str());
    qDebug() << "file_path: " << (file_path != nullptr ? file_path->c_str() : "null");

    if (file_path == nullptr || file_path->empty()) {
        qDebug() << "Not found file for path: " << path;
        return not_found(req, res);
    }

    acl::ifstream fp;
    if (!fp.open_read(file_path->c_str())) {
        qDebug() << "Open file " << file_path->c_str() << " error " << acl::last_serror();
        return not_found(req, res);
    }

    auto length = fp.fsize();
    if (length < 0) {
        qDebug() << "Invalid file size: " << length;
        return not_found(req, res);
    }

    res.setContentLength((size_t) length);
    res.setContentType("application/octet-stream");
    res.setKeepAlive(req.isKeepAlive());

    char buf[4096];
    while (!fp.eof()) {
        int ret = fp.read(buf, sizeof(buf), false);
        if (ret == -1) {
            qDebug() << "Read over, total size: " << length;
            break;
        }
        length += ret;
        if (!res.write(buf, (size_t) ret)) {
            qDebug() << "Write error to client: " << acl::last_serror();
            return false;
        }
    }

    return req.isKeepAlive();
}

static void startupCallback() {
    qDebug() << "Begin schedule gui fiber!";
    acl::fiber::winapi_hook();	// Enable hooking the system IO API.
    acl::fiber::schedule_gui(); // Won't return until schedule finished.
    qDebug() << "schedule gui fiber end!";
}

static void app_run(int argc, char **argv) {
    QApplication app(argc, argv);
    http_service service;
    MainWindow w(nullptr, service);

    service.Get("/", [](HttpRequest&, HttpResponse& res) {
        acl::string buf("hello world!\r\n");
        return res.write(buf, buf.size());
    }).Get("/test", [](HttpRequest&, HttpResponse& res) {
        acl::string buf("test: ok!\r\n");
        return res.write(buf, buf.size());
    }).Default([&w](const char* path, HttpRequest& req, HttpResponse& res) {
        qDebug() << "Begin handle path: " << path;
        return handleDownload(w, path, req, res);
    });

    w.show();

    QTimer::singleShot(0, startupCallback);
    app.exec();
}

int main(int argc, char *argv[]) {
    acl::acl_cpp_init();
    app_run(argc, argv);
    return 0;
}
